#include <iostream>
#include <cstring>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <pthread.h>
#include "pthreadpool.hpp"
#include "Task.hpp"
#include "log.hpp"
using namespace std;
class Server
{
public:
    Server(const uint16_t &port) : _fd(-1), _port(port) {}
    void init()
    {
        _fd = socket(AF_INET, SOCK_STREAM, 0);
        if (_fd == -1)
        {
            cerr << strerror(errno) << endl;
            exit(1);
        }
        logMessage(NORMAL, "socket success");
        struct sockaddr_in addr;
        bzero(&addr, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = INADDR_ANY;
        addr.sin_port = htons(_port);
        int n = bind(_fd, (struct sockaddr *)&addr, sizeof(addr));
        if (n == -1)
        {
            logMessage(ERROR, strerror(errno));
            exit(2);
        }
        logMessage(NORMAL, "bind success");

        n = listen(_fd, 5);
        if (n < 0)
        {
            cerr << strerror(errno) << endl;
            exit(2);
        }
        logMessage(NORMAL, "listen success");
    }
    // 进程版
    // void start()
    // {
    //     signal(SIGCHLD, SIG_IGN);
    //     while (1)
    //     {
    //         struct sockaddr_in addr;
    //         socklen_t len = sizeof(addr);
    //         int socket = accept(_fd, (struct sockaddr *)&addr, &len);
    //         cout << "accept successs : " << socket << endl;
    //         if (socket == -1)
    //         {
    //             cerr << strerror(errno) << endl;
    //             continue;
    //         }
    //         pid_t id = fork();
    //         if (id == 0)
    //         {
    //             close(_fd);
    //             serviceIO(socket);
    //             close(socket);
    //             exit(0);
    //         }
    //         close(socket);
    //     }
    // }
    // void serviceIO(const int &fd)
    // {
    //     while (1)
    //     {
    //         char buffer[1024];
    //         ssize_t size = read(fd, buffer, sizeof(buffer) - 1);
    //         if (size > 0)
    //         {
    //             buffer[size] = 0;
    //             cout << "[Client] : " << buffer << endl;
    //             string messages = buffer;
    //             ssize_t ret = write(fd, messages.c_str(), messages.size());
    //             if (ret < 0)
    //             {
    //                 cerr << strerror(errno) << endl;
    //             }
    //         }
    //         else if (size == 0)
    //         {
    //             cerr << "Client quit" << endl;
    //             break;
    //         }
    //         else
    //         {
    //             cerr << strerror(errno) << endl;
    //             exit(3);
    //         }
    //     }
    // }

    // 线程版
    // void start()
    // {
    //     while (1)
    //     {
    //         struct sockaddr_in addr;
    //         socklen_t len = sizeof(addr);
    //         int socket = accept(_fd, (struct sockaddr *)&addr, &len);
    //         cout << "accept successs : " << socket << endl;
    //         if (socket == -1)
    //         {
    //             cerr << strerror(errno) << endl;
    //             continue;
    //         }
    //         pthread_t t;
    //         pthread_create(&t, nullptr, serviceIO, (void *)&socket);
    //         pthread_detach(t);
    //     }
    // }
    // static void *serviceIO(void *arg)
    // {
    //     int fd = *(static_cast<int *>(arg));
    //     while (1)
    //     {
    //         char buffer[1024];
    //         ssize_t size = read(fd, buffer, sizeof(buffer) - 1);
    //         if (size > 0)
    //         {
    //             buffer[size] = 0;
    //             cout << "[Client] : " << buffer << endl;
    //             string messages = buffer;
    //             ssize_t ret = write(fd, messages.c_str(), messages.size());
    //             if (ret < 0)
    //             {
    //                 cerr << strerror(errno) << endl;
    //             }
    //         }
    //         else if (size == 0)
    //         {
    //             cerr << "Client quit" << endl;
    //             break;
    //         }
    //         else
    //         {
    //             cerr << strerror(errno) << endl;
    //             exit(3);
    //         }
    //     }
    //     close(fd);
    //     return nullptr;
    // }
    void start()
    {
        pthreadPool<Task>::getInstance()->run();
        while (1)
        {
            struct sockaddr_in addr;
            socklen_t len = sizeof(addr);
            int socket = accept(_fd, (struct sockaddr *)&addr, &len);
            if (socket == -1)
            {
                cerr << strerror(errno) << endl;
                continue;
            }
            logMessage(NORMAL, "accept successs : %d", socket);
            pthreadPool<Task>::getInstance()->push(Task(socket, serviceIO));
        }
    }

    ~Server()
    {
        close(_fd);
    }

private:
    int _fd;
    uint16_t _port;
};